#include "rs485_app.h"
#include "485_protocol.h"
#include "flash_api.h"
#include "sound_app.h"

static Rs485BitStatus_t Rs485BitStatus = {0};
extern void PromptIntoIoBoardUpdataFirmware(void);
bool ClearRs485BitStatus(void)
{
    memset(&Rs485BitStatus, 0, sizeof(Rs485BitStatus));
    return true;
}

bool Rs485BuildOpenSpecificFloorMessage(void *parmIn, uint8_t *pMessageOut, uint16_t *pSizeOut, uint32_t *pResponseTimeOut)
{
    bool MessageConstructionState = false;

    if ((pMessageOut != NULL) && (pSizeOut != NULL) && (pResponseTimeOut != NULL))
    {

        switch (Rs485BitStatus.StepsOfSending)
        {
        case SEND_STEP_ONE:
        {
            MessageConstructionState = BuildOpenSpecificFoorFrameCallback(parmIn, pMessageOut, pSizeOut);
        }
        break;

        default:
            break;
        }
    }

    return MessageConstructionState;
}

uint8_t Rs485ParsingOpenSpecificFloorMessage(const void *pDataIn, uint16_t pDataSizeIn)
{
    uint8_t ParsingResults = RS485_EXECUTE_ERROR;
    RS485MessageParsingResult_t ParsingState = RS485_PARSING_ERROR;

    if (pDataIn != NULL)
    {
        ParsingState = ParsingOpenSpecificFoorFrameCallback((uint8_t *)pDataIn, pDataSizeIn);
        if (ParsingState == RS485_PARSING_SUCCESS)
        {
            ParsingResults = RS485_EXECUTE_OVER;
            Rs485BitStatus.StepsOfSending = RS485_ALL_COMMAND_EXECUTED;
        }
    }

    return ParsingResults;
}

bool Rs485BuildGetVersionMessage(void *parmIn, uint8_t *pMessageOut, uint16_t *pSizeOut, uint32_t *pResponseTimeOut)
{
    bool MessageConstructionState = false;

    if ((pMessageOut != NULL) && (pSizeOut != NULL) && (pResponseTimeOut != NULL))
    {

        switch (Rs485BitStatus.StepsOfSending)
        {
        case SEND_STEP_ONE:
        {
            MessageConstructionState = BuildGetVersionFrameCallback(parmIn, pMessageOut, pSizeOut);
        }
        break;

        default:
            break;
        }
    }

    return MessageConstructionState;
}

uint8_t Rs485ParsingGetVersionMessage(const void *pDataIn, uint16_t pDataSizeIn)
{
    uint8_t ParsingResults = RS485_EXECUTE_ERROR;
    RS485MessageParsingResult_t ParsingState = RS485_PARSING_ERROR;

    if (pDataIn != NULL)
    {
        ParsingState = ParsingGetVersionFrameCallback((uint8_t *)pDataIn, pDataSizeIn);
        if (ParsingState == RS485_PARSING_SUCCESS)
        {
            ParsingResults = RS485_EXECUTE_OVER;
            Rs485BitStatus.StepsOfSending = RS485_ALL_COMMAND_EXECUTED;
        }
    }

    return ParsingResults;
}

bool Rs485BuildOpenEmergencyModeMessage(void *parmIn, uint8_t *pMessageOut, uint16_t *pSizeOut, uint32_t *pResponseTimeOut)
{
    bool MessageConstructionState = false;

    if ((pMessageOut != NULL) && (pSizeOut != NULL) && (pResponseTimeOut != NULL))
    {

        MessageConstructionState = BuildOpenEmergencyModeFrameCallback(parmIn, pMessageOut, pSizeOut);
    }

    return MessageConstructionState;
}

uint8_t Rs485ParsingOpenEmergencyModeMessage(const void *pDataIn, uint16_t pDataSizeIn)
{
    uint8_t ParsingResults = RS485_EXECUTE_ERROR;
    RS485MessageParsingResult_t ParsingState = RS485_PARSING_ERROR;

    if (pDataIn != NULL)
    {
        ParsingState = ParsingOpenEmergencyModeFrameCallback((uint8_t *)pDataIn, pDataSizeIn);

        if (ParsingState == RS485_PARSING_SUCCESS)
        {
            ParsingResults = RS485_EXECUTE_OVER;
            Rs485BitStatus.StepsOfSending = RS485_ALL_COMMAND_EXECUTED;
        }
    }

    return ParsingResults;
}

extern uint32_t ProtocolGetFileSumSize(void);
extern void SetIoBoarGetOtaStatusNumberOfRetriesAndIngerval(void);
bool Rs485BuildIoBoardFirmwareTransMessage(void *parmIn, uint8_t *pMessageOut, uint16_t *pSizeOut, uint32_t *pResponseTimeOut)
{

    bool MessageConstructionState = false;

    if ((pMessageOut != NULL) && (pSizeOut != NULL) && (pResponseTimeOut != NULL))
    {
        switch (Rs485BitStatus.StepsOfSending)
        {
        case SEND_STEP_ONE:
        {
            // 发送前的准备工作
            IoBoardFirmwareInfo_t *IoBoardFirmwareInfo = GetBoardFirmwareInfoPtr();
            if (IoBoardFirmwareInfo->CurrentSendPackageSeqNumber == 0) // 这是第一个包
            {
                uint32_t FirmwareSize = ProtocolGetFileSumSize();
                if (FirmwareSize == 0)
                {
                    IoBoardFirmwareInfo->IoBoardFirmwareSumSize = FlashGetIoBoardFirmwareMaxFileSize(); // 传输里面整个flash分区的大小
                }
                else
                {
                    IoBoardFirmwareInfo->IoBoardFirmwareSumSize = FirmwareSize; // 协议里面获取的大小
                }
                // 设置每个包发送的数据大小
                if (IoBoardFirmwareInfo->IoBoardFirmwareSumSize - IoBoardFirmwareInfo->SentDataSize < MESSAGE_DATA_PACKET_LENGTH_S)
                {
                    IoBoardFirmwareInfo->SinglePackageSendBufferSize = IoBoardFirmwareInfo->IoBoardFirmwareSumSize - IoBoardFirmwareInfo->SentDataSize;
                }
                else
                {
                    IoBoardFirmwareInfo->SinglePackageSendBufferSize = MESSAGE_DATA_PACKET_LENGTH_S;
                }
                // 计算出总发送的包数量
                if (IoBoardFirmwareInfo->IoBoardFirmwareSumSize % IoBoardFirmwareInfo->SinglePackageSendBufferSize)
                {
                    IoBoardFirmwareInfo->SumSentPackageNumber = (IoBoardFirmwareInfo->IoBoardFirmwareSumSize / IoBoardFirmwareInfo->SinglePackageSendBufferSize) + 1;
                }
                else
                {
                    IoBoardFirmwareInfo->SumSentPackageNumber = (IoBoardFirmwareInfo->IoBoardFirmwareSumSize / IoBoardFirmwareInfo->SinglePackageSendBufferSize);
                }
                // 计算出第一个包
                IoBoardFirmwareInfo->CurrentSendPackageSeqNumber = 0;
                // 设置当前发送的包的偏移
                IoBoardFirmwareInfo->SentDataSize = 0;
                // 从flash读取固件
                FlashReadIoBoardFirmware(IoBoardFirmwareInfo->SentDataSize, IoBoardFirmwareInfo->SinglePackageSendBuffer, IoBoardFirmwareInfo->SinglePackageSendBufferSize);
            }
            else
            {
                // 设置每个包发送的数据大小
                if (IoBoardFirmwareInfo->IoBoardFirmwareSumSize - IoBoardFirmwareInfo->SentDataSize < MESSAGE_DATA_PACKET_LENGTH_S)
                {
                    IoBoardFirmwareInfo->SinglePackageSendBufferSize = IoBoardFirmwareInfo->IoBoardFirmwareSumSize - IoBoardFirmwareInfo->SentDataSize;
                }
                else
                {
                    IoBoardFirmwareInfo->SinglePackageSendBufferSize = MESSAGE_DATA_PACKET_LENGTH_S;
                }
                // 读取固件的数
                FlashReadIoBoardFirmware(IoBoardFirmwareInfo->SentDataSize, IoBoardFirmwareInfo->SinglePackageSendBuffer, IoBoardFirmwareInfo->SinglePackageSendBufferSize);
            }
            MessageConstructionState = BuildFirmwareTransFrameCallback(parmIn, pMessageOut, pSizeOut);
            IoBoardFirmwareInfo->SentDataSize += IoBoardFirmwareInfo->SinglePackageSendBufferSize;
        }
        break;

        case SEND_STEP_TWO: // 发送查询运行状态
        {
            // todo: 设置发送间隔和发送数量
            SetIoBoarGetOtaStatusNumberOfRetriesAndIngerval();
            MessageConstructionState = BuildQueryIoBoardFirmwareStatusCallback(parmIn, pMessageOut, pSizeOut);
        }
        break;

        case SEND_STEP_THREE:
        {
            MessageConstructionState = BuildGetVersionFrameCallback(parmIn, pMessageOut, pSizeOut);
        }
        break;

        case SEND_STEP_FOUR:
        {
            MessageConstructionState = BuildQueryIoBoardMacAddressCallback(NULL, pMessageOut, pSizeOut);
        }
        break;

        default:
            break;
        }
    }

    return MessageConstructionState;
}

uint8_t Rs485ParsingIoBoardFirmwareTransMessage(const void *pDataIn, uint16_t pDataSizeIn)
{
    uint8_t ParsingResults = RS485_EXECUTE_ERROR;
    RS485MessageParsingResult_t ParsingState = RS485_PARSING_ERROR;

    if (pDataIn != NULL)
    {
        switch (Rs485BitStatus.StepsOfSending)
        {
        case SEND_STEP_ONE:
        {
            ParsingState = ParsingFirmwareTransFrameCallback((uint8_t *)pDataIn, pDataSizeIn);
            if (ParsingState == RS485_PARSING_SUCCESS)
            {
                IoBoardFirmwareInfo_t *IoBoardFirmwareInfo = GetBoardFirmwareInfoPtr();
                IoBoardFirmwareInfo->CurrentSendPackageSeqNumber++;
                if (IoBoardFirmwareInfo->CurrentSendPackageSeqNumber > IoBoardFirmwareInfo->SumSentPackageNumber - 1)
                {
                    /** 接收固件完成 **/
                    Rs485BitStatus.StepsOfSending = SEND_STEP_TWO;
                }
                else
                {
                    /** 接收固件未完成 **/
                    Rs485BitStatus.StepsOfSending = SEND_STEP_ONE;
                }
                ParsingResults = RS485_EXECUTE_SUCCESS;
            }
        }
        break;

        case SEND_STEP_TWO:
        {
            ParsingState = ParsingQueryIoBoardFirmwareStatusCallback((uint8_t *)pDataIn, pDataSizeIn);
            if (ParsingState == RS485_PARSING_SUCCESS)
            {
                uint8_t *RunningStatus = (uint8_t *)pDataIn;
                if (RunningStatus[0] == R_OTA_RUNNING)
                {
                    Rs485BitStatus.StepsOfSending = SEND_STEP_TWO;
                    ParsingResults = RS485_EXECUTE_SUCCESS;
                }
                else if (RunningStatus[0] == R_RUNNING)
                {
                    Rs485BitStatus.StepsOfSending = SEND_STEP_THREE;
                    ParsingResults = RS485_EXECUTE_SUCCESS;
                }
                else
                {
                    ParsingResults = RS485_EXECUTE_OVER;
                }
            }
        }
        break;

        case SEND_STEP_THREE:
        {
            ParsingState = ParsingGetVersionFrameCallback((uint8_t *)pDataIn, pDataSizeIn);
            if (ParsingState == RS485_PARSING_SUCCESS)
            {
                // 升级成功
                uint8_t SupportIoBoardNumber = GetEleControlBoardNumber();
                uint8_t CurrentUpdateBoardId = GetCurrentUpdateBoardId();
                SetCurrentUpdateBoardStatus(UPDATE_BOARD_STATUS_SUCCESS);
                PRINT("SEND_STEP_THREE ParsingGetVersionFrameCallback SupportIoBoardNumber = %d, CurrentUpdateBoardId = %d\r\n", SupportIoBoardNumber, CurrentUpdateBoardId);
                if ( CurrentUpdateBoardId == (SupportIoBoardNumber - 1) ) // 结束
                {
                    PRINT("------------ok----------------->\r\n");
                    SetIoBoardFirmwareExistFlag(false);
                    SetCurrentUpdateBoardId(0);
                    PromptIntoIoBoardUpdataFirmware();
                }
                
                // 播放清除卡音效
                PlaySettingStatusAudio(true);
                ParsingResults = RS485_EXECUTE_SUCCESS;
                Rs485BitStatus.StepsOfSending = SEND_STEP_FOUR;
            }
        }
        break;

        case SEND_STEP_FOUR:
        {
            ParsingState = ParsingQueryIoBoardMacAddressCallback((uint8_t *)pDataIn, pDataSizeIn);
            if (ParsingState == RS485_PARSING_SUCCESS)
            {
                ParsingResults = RS485_EXECUTE_OVER;
                Rs485BitStatus.StepsOfSending = RS485_ALL_COMMAND_EXECUTED;
            }
        }
        break;

        default:
            break;
        }
    }

    return ParsingResults;
}

bool Rs485BuildQueryIoBoardFirmwareStatusMessage(void *parmIn, uint8_t *pMessageOut, uint16_t *pSizeOut, uint32_t *pResponseTimeOut)
{

    bool MessageConstructionState = false;

    if ((pMessageOut != NULL) && (pSizeOut != NULL) && (pResponseTimeOut != NULL))
    {
        switch (Rs485BitStatus.StepsOfSending)
        {
        case SEND_STEP_ONE:
        {
            MessageConstructionState = BuildQueryIoBoardFirmwareStatusCallback(parmIn, pMessageOut, pSizeOut);
        }
        break;

        default:
            break;
        }
    }

    return MessageConstructionState;
}

uint8_t Rs485ParsingQueryIoBoardFirmwareStatusMessage(const void *pDataIn, uint16_t pDataSizeIn)
{
    uint8_t ParsingResults = RS485_EXECUTE_ERROR;

    RS485MessageParsingResult_t ParsingState = RS485_PARSING_ERROR;

    if (pDataIn != NULL)
    {
        ParsingState = ParsingQueryIoBoardFirmwareStatusCallback((uint8_t *)pDataIn, pDataSizeIn);
        if (ParsingState == RS485_PARSING_SUCCESS)
        {
            ParsingResults = RS485_EXECUTE_OVER;
            Rs485BitStatus.StepsOfSending = RS485_ALL_COMMAND_EXECUTED;
        }
    }

    return ParsingResults;
}

bool Rs485BuildQueryIoBoardMacAddressMessage(void *parmIn, uint8_t *pMessageOut, uint16_t *pSizeOut, uint32_t *pResponseTimeOut)
{
    bool MessageConstructionState = false;

    if ((pMessageOut != NULL) && (pSizeOut != NULL) && (pResponseTimeOut != NULL))
    {
        uint8_t IoBoardAddress[MAC_ADDR_CODING_LENGTH] = {0};
        GetDestinMacAddress(IoBoardAddress);
        MessageConstructionState = BuildQueryIoBoardMacAddressCallback(NULL, pMessageOut, pSizeOut);
        return MessageConstructionState;
    }
    return false;
}

uint8_t Rs485ParsingQueryIoBoardMacAddressMessage(const void *pDataIn, uint16_t pDataSizeIn)
{
    uint8_t ParsingResults = RS485_EXECUTE_ERROR;

    RS485MessageParsingResult_t ParsingState = RS485_PARSING_ERROR;

    IoboardDeviceInfo_t *IoboardDeviceInfoTable = GetIoBoardDeviceInfoTablePtr();
    if (pDataIn != NULL)
    {
        ParsingState = ParsingQueryIoBoardMacAddressCallback((uint8_t *)pDataIn, pDataSizeIn);
        if (ParsingState == RS485_PARSING_SUCCESS)
        {
            uint8_t IoBoardAddress[MAC_ADDR_CODING_LENGTH] = {0};
            GetDestinMacAddress(IoBoardAddress);

            ParsingResults = RS485_EXECUTE_OVER;
            Rs485BitStatus.StepsOfSending = RS485_ALL_COMMAND_EXECUTED;
        }
    }
    return ParsingResults;
}

bool Rs485BuildSetBoardSelfTestFrameMessage(void *parmIn, uint8_t *pMessageOut, uint16_t *pSizeOut, uint32_t *pResponseTimeOut)
{

    bool MessageConstructionState = false;

    if ((pMessageOut != NULL) && (pSizeOut != NULL) && (pResponseTimeOut != NULL))
    {

        MessageConstructionState = BuildSetBoardSelfTestFrameCallback(parmIn, pMessageOut, pSizeOut);
    }

    return MessageConstructionState;
}

uint8_t Rs485ParsingSetBoardSelfTestFrameMessage(const void *pDataIn, uint16_t pDataSizeIn)
{
    uint8_t ParsingResults = RS485_EXECUTE_ERROR;

    RS485MessageParsingResult_t ParsingState = RS485_PARSING_ERROR;

    if (pDataIn != NULL)
    {
        ParsingState = ParsingSetBoardSelfTestFrameCallback((uint8_t *)pDataIn, pDataSizeIn);
        if (ParsingState == RS485_PARSING_SUCCESS)
        {
            ParsingResults = RS485_EXECUTE_OVER;
            Rs485BitStatus.StepsOfSending = RS485_ALL_COMMAND_EXECUTED;
        }
    }

    return ParsingResults;
}

// 构建设置io板消防工作模式命令  0730 new
bool Rs485BuildSetBoardFireAlarmWorkModeFrameMessage(void *parmIn, uint8_t *pMessageOut, uint16_t *pSizeOut, uint32_t *pResponseTimeOut)
{

    bool MessageConstructionState = false;
    if ((pMessageOut != NULL) && (pSizeOut != NULL) && (pResponseTimeOut != NULL))
    {
        MessageConstructionState = BuildSetBoardFireAlarmWorkModeFrameCallback(parmIn, pMessageOut, pSizeOut);
    }
    return MessageConstructionState;
}

// 解析设置io板消防工作模式命令 0730 new
uint8_t Rs485ParsingSetBoardFireAlarmWorkModeFrameCallback(const void *pDataIn, uint16_t pDataSizeIn)
{
    uint8_t ParsingResults = RS485_EXECUTE_ERROR;
    RS485MessageParsingResult_t ParsingState = RS485_PARSING_ERROR;

    if (pDataIn != NULL)
    {
        ParsingState = ParsingSetBoardFireAlarmWorkModeFrameCallback((uint8_t *)pDataIn, pDataSizeIn);
        if (ParsingState == RS485_PARSING_SUCCESS)
        {
            ParsingResults = RS485_EXECUTE_OVER;
            Rs485BitStatus.StepsOfSending = RS485_ALL_COMMAND_EXECUTED;
        }
    }
    return ParsingResults;
}

// 构建查询io板消防状态的报文 0730 new
bool Rs485BuildQueryBoardFireAlarmStatusFrameMessage(void *parmIn, uint8_t *pMessageOut, uint16_t *pSizeOut, uint32_t *pResponseTimeOut)
{
    bool MessageConstructionState = false;
    if ((pMessageOut != NULL) && (pSizeOut != NULL) && (pResponseTimeOut != NULL))
    {
        MessageConstructionState = BuildQueryBoardFireAlarmStatusFrameCallback(parmIn, pMessageOut, pSizeOut);
    }
    return MessageConstructionState;
}

// 解析查询io板消防状态命令 0730 new
uint8_t Rs485ParsingQueryBoardFireAlarmStatusFrameCallback(const void *pDataIn, uint16_t pDataSizeIn)
{
    uint8_t ParsingResults = RS485_EXECUTE_ERROR;
    RS485MessageParsingResult_t ParsingState = RS485_PARSING_ERROR;

    if (pDataIn != NULL)
    {
        ParsingState = ParsingQueryBoardFireAlarmStatusFrameCallback((uint8_t *)pDataIn, pDataSizeIn);
        if (ParsingState == RS485_PARSING_SUCCESS)
        {
            ParsingResults = RS485_EXECUTE_OVER;
            Rs485BitStatus.StepsOfSending = RS485_ALL_COMMAND_EXECUTED;
        }
    }
    return ParsingResults;
}
